#ifndef _BASE_MUTEX_TEST_H_
#define _BASE_MUTEX_TEST_H_

#include "Base.Mutex.h"
#include "Base.MutexLocker.h"
#include "Base.Thread.h"
#include "Meta.Functor.h"

#ifdef _POSIX_VERSION
#include "unistd.h"
#elif WIN32
#include "windows.h"
#endif

namespace BaseMutexTest
{

      class SyncClass
	{
	public:
	      SyncClass()
		{
			value = 0;
			setValueLock = false;
		}
		
		void SetValue(int x)
		{
			setValueLock = true;
                        SetLockedValue(x);
			setValueLock = false;
		}

            void SetLockedValue(int x)
            {
                  LOCK_MUTEX(mutex);
			value = x;
            }

		void Lock()
		{
			mutex.lock();
		}
		
		void Unlock()
		{
			mutex.unlock();
		}
		
		int GetValue()
		{
			return value;
		}
		
		bool GetSetValueLockStatus()
		{
			return setValueLock;
		}
		
	private:
		
		bool setValueLock;
		
		Maha::Base::Mutex mutex;
		
		int value;
	};



TEST(MutexTest, lockAndUnlock)
{
	using namespace BaseMutexTest;
	using namespace Maha::Meta;
	
	SyncClass syncClass;

      syncClass.Lock();
      syncClass.Unlock();
}

TEST(MutexTest, lockAndUnlockVerifying)
{
	using namespace BaseMutexTest;
	using namespace Maha::Meta;
	using namespace Maha::Base;
	
	SyncClass syncClass;
	
	Functor<void, TYPELIST_1(int)> fctor(&syncClass, &SyncClass::SetValue);
	
	Task<void, Functor<void, TYPELIST_1(int)>, TYPELIST_1(int)> task(fctor, 777);
	
	syncClass.SetValue(555);
	syncClass.Lock();
	Thread thread(task);
	
	int n = 0;
	while(false == syncClass.GetSetValueLockStatus() && n < 1000)
	{
#ifdef _POSIX_VERSION
		usleep(1000);
#elif WIN32
		Sleep(1);
#endif
		n++;
	}
	
	ASSERT_EQ(true, syncClass.GetSetValueLockStatus());
	ASSERT_EQ(555, syncClass.GetValue());
	syncClass.Unlock();
	
	n = 0;
	while(true == syncClass.GetSetValueLockStatus() && n < 1000)
	{
#ifdef _POSIX_VERSION
		usleep(1000);
#elif WIN32
		Sleep(1);
#endif
		n++;
	}
	
	ASSERT_EQ(false, syncClass.GetSetValueLockStatus());
	ASSERT_EQ(777, syncClass.GetValue());
}


}


#endif // _BASE_MUTEX_TEST_H_
